package org.easystub;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.InvocationHandler;

import java.lang.reflect.Proxy;
import java.lang.reflect.Method;

public class ProxyFactory {


    public <T> T createProxyInstance(InvocationHandlerParameters<T> params) {
        T proxy;
        if(params.getStubbedClass().isInterface()) {
            proxy = jdkProxy(params);
        } else {
            proxy = cglibProxy(params);
        }

        params.getReporter().setReportingObject(proxy);
        return proxy;
    }

    @SuppressWarnings("unchecked")
    private <T> T cglibProxy(InvocationHandlerParameters<T> params) {
        final StubInvocationHandler handler = new StubInvocationHandler(params);
        return (T) Enhancer.create(params.getStubbedClass(), new InvocationHandler() {
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                return handler.invoke(o, method, objects);
            }
        });
    }

    @SuppressWarnings("unchecked")
    private <T> T jdkProxy(InvocationHandlerParameters<T> params) {
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{params.getStubbedClass()},
                new StubInvocationHandler(params));
    }

}
